FinTech Homework
Due date: 2023/10/15 23:59:59
Trading Strategies Using Technical Indicators
In this homework, you need to design a trading strategy to maximize the return of stock trading over a future period of time.
- Target stock: 元大台灣50 (0050.TW)
- How to obtain historical stock prices: 下載 Yahoo財經 中的歷史數據
- Price data of 元大台灣50 (0050.TW) obtained via the above method
(You can download it as a single CSV file, with specified time period of interest.)
- We shall use the price of "Adj Close" for trading.
- Your trading strategy
- Your trading strategy can only take the currently available historical data for reaching a decision of "buy" or "sell".
- Your strategy should based on technical indicators (MA, RSI, etc) for maximizing the return. (You can define your own technical indicators if necessary.)
- Your strategy will be used to determine the return over the evaluation period of 10 weeks: 2023/10/16 ~ 2023/12/22.
- Here is a file list of example code for you to start with. The readme.txt of the example code folder is shown next:
This is the readme.txt file in the example code for HW of "Trading using technical indicators".
myStrategy.py:
The only script you need to submit, which returns the action of "buy" or "sell".
The parameters of this function are optimized by "bestParamByExhaustiveSearch.py".
bestParamByExhaustiveSearch.py:
This script obtains the best parameters by exhaustive search.
You can then insert the best parameters into myStrategy.py for evaluation.
To run it:
python bestParamByExhaustiveSearch.py 0050.TW-short.csv
rrEstimate.py:
This script calls myStrategy.py to obtain RR (return rate) for a given price vectors.
Our judge will use a similiar script to evaluate your submission.
To run it:
python rrEstimate.py 0050.TW-short.csv
*.csv
0050.TW-short.csv: Price of 0050 over the past 5 years
- Submission
- You only need to submit the function "myStrategy.py".
Your design flowchart should be like this:
- Determine the technical indicator (TI) you want to use. (You can use more than one TIs.)
- Define the trading strategy using the TIs, with some modifiable parameters for optimizing the return.
- Optimzie the return using the historical price data.
- Use the obtained parameters for trading over a future period of time.
For instance, in the following example code, we use MA (moving average) as the TI, with the parameters of window size, alpha, beta. Then we optimize these parameters by exhaustive search, as shown in bestParamViaExhaustiveSearch.py:
import sys
import numpy as np
import pandas as pd
# Decision of the current day by the current price, with 3 modifiable parameters
def myStrategy(pastPriceVec, currentPrice, windowSize, alpha, beta):
import numpy as np
action=0 # action=1(buy), -1(sell), 0(hold), with 0 as the default action
dataLen=len(pastPriceVec) # Length of the data vector
if dataLen==0:
return action
# Compute ma
if dataLenalpha: # If price-ma > alpha ==> buy
action=1
elif (currentPrice-ma)<-beta: # If price-ma < -beta ==> sell
action=-1
return action
# Compute return rate over a given price vector, with 3 modifiable parameters
def computeReturnRate(priceVec, windowSize, alpha, beta):
capital=1000 # Initial available capital
capitalOrig=capital # original capital
dataCount=len(priceVec) # day size
suggestedAction=np.zeros((dataCount,1)) # Vec of suggested actions
stockHolding=np.zeros((dataCount,1)) # Vec of stock holdings
total=np.zeros((dataCount,1)) # Vec of total asset
realAction=np.zeros((dataCount,1)) # Real action, which might be different from suggested action. For instance, when the suggested action is 1 (buy) but you don't have any capital, then the real action is 0 (hold, or do nothing).
# Run through each day
for ic in range(dataCount):
currentPrice=priceVec[ic] # current price
suggestedAction[ic]=myStrategy(priceVec[0:ic], currentPrice, windowSize, alpha, beta) # Obtain the suggested action
# get real action by suggested action
if ic>0:
stockHolding[ic]=stockHolding[ic-1] # The stock holding from the previous day
if suggestedAction[ic]==1: # Suggested action is "buy"
if stockHolding[ic]==0: # "buy" only if you don't have stock holding
stockHolding[ic]=capital/currentPrice # Buy stock using cash
capital=0 # Cash
realAction[ic]=1
elif suggestedAction[ic]==-1: # Suggested action is "sell"
if stockHolding[ic]>0: # "sell" only if you have stock holding
capital=stockHolding[ic]*currentPrice # Sell stock to have cash
stockHolding[ic]=0 # Stocking holding
realAction[ic]=-1
elif suggestedAction[ic]==0: # No action
realAction[ic]=0
else:
assert False
total[ic]=capital+stockHolding[ic]*currentPrice # Total asset, including stock holding and cash
returnRate=(total[-1]-capitalOrig)/capitalOrig # Return rate of this run
return returnRate
if __name__=='__main__':
returnRateBest=-1.00 # Initial best return rate
df=pd.read_csv(sys.argv[1]) # read stock file
adjClose=df["Adj Close"].values # get adj close as the price vector
windowSizeMin=11; windowSizeMax=20; # Range of windowSize to explore
alphaMin=-5; alphaMax=5; # Range of alpha to explore
betaMin=-5; betaMax=5 # Range of beta to explore
# Start exhaustive search
for windowSize in range(windowSizeMin, windowSizeMax+1): # For-loop for windowSize
print("windowSize=%d" %(windowSize))
for alpha in range(alphaMin, alphaMax+1): # For-loop for alpha
print("\talpha=%d" %(alpha))
for beta in range(betaMin, betaMax+1): # For-loop for beta
print("\t\tbeta=%d" %(beta), end="") # No newline
returnRate=computeReturnRate(adjClose, windowSize, alpha, beta) # Start the whole run with the given parameters
print(" ==> returnRate=%f " %(returnRate))
if returnRate > returnRateBest: # Keep the best parameters
windowSizeBest=windowSize
alphaBest=alpha
betaBest=beta
returnRateBest=returnRate
print("Best settings: windowSize=%d, alpha=%d, beta=%d ==> returnRate=%f" %(windowSizeBest,alphaBest,betaBest,returnRateBest)) # Print the best result
You can run the above program on "0050.TW-short.csv" by typing "python bestParamByExhaustiveSearch.py 0050.TW-short.csv" to obtain the best return rate:
Best settings: windowSize=14, alpha=0, beta=-5 ==> returnRate=0.815243
Therefore you can use these parameter values in the program "myStrategy.py", as follows
def myStrategy(pastPriceVec, currentPrice):
# Explanation of my approach:
# 1. Technical indicator used: MA
# 2. if price-ma>alpha ==> buy
# if price-ma<-beta ==> sell
# 3. Modifiable parameters: alpha, beta, and window size for MA
# 4. Use exhaustive search to obtain these parameter values (as shown in bestParamByExhaustiveSearch.py)
import numpy as np
# Set best parameters
windowSize=14
alpha=0
beta=-5
action=0 # action=1(buy), -1(sell), 0(hold), with 0 as the default action
dataLen=len(pastPriceVec) # Length of the data vector
if dataLen==0:
return action
# Compute MA
if dataLenalpha: # If price-ma > alpha ==> buy
action=1
elif (currentPrice-ma)<-beta: # If price-ma < -beta ==> sell
action=-1
return action
You can then try the trading strategy on "0050.TW-short.csv" by typing "python rrEstimate.py 0050.TW-short.csv" to get the result:
rr=81.524342%
Other notes:
- FAQ of the HW, maintained by TA, including
- Versions of installd packages
- Hardware specs
- Benchmark for timing test
- Max time of each call to your function
- ...
- Each call to myStrategy() should last no more than n sec (where n is specified in the above FAQ), otherwise it will be killed and the output of the function is 0 by default.
This function will be called by TA's program during each day of the evaluation period.
- You can try other complicated TIs (such as deep neural networks), but you should keep in mind that complicated models do not necessarily perform well for test data. You always need to strike a balance between model complexity and available data amount.
- Evaluation criteria:
- 50%: Ranking in return rate
- 50%: A PDF report describing your work on this HW.
- 15%: The TI you adopt and why you choose this TI. And how you use the TI for trading.
- 17%: What are the modified parameters of your strategy, and how do you fine tune the parameters.
- 18%: Any other things you have done to optimize your strategy.